﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;
using WinRtBehaviors;

namespace F2S.LINQ2LinkedIn.Client.Behaviors
{
    public class DataStateBehavior : Behavior<Control>
    {
        /// <summary>Backing DP for the Binding property</summary>
        public static readonly DependencyProperty BindingProperty = DependencyProperty.Register("Binding",
            typeof (Binding),
            typeof (DataStateBehavior), new PropertyMetadata(null, DataStateBehavior.HandleBindingChanged));

        /// <summary>Backing DP for the Value property</summary>
        public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof (object),
            typeof (DataStateBehavior), new PropertyMetadata(null, DataStateBehavior.HandleValueChanged));

        /// <summary>Backing DP for the TrueState property</summary>
        public static readonly DependencyProperty TrueStateProperty = DependencyProperty.Register("TrueState",
            typeof (string), typeof (DataStateBehavior), new PropertyMetadata(null));

        /// <summary>Backing DP for the FalseState property</summary>
        public static readonly DependencyProperty FalseStateProperty = DependencyProperty.Register("FalseState",
            typeof (string), typeof (DataStateBehavior), new PropertyMetadata(null));

        public static readonly DependencyProperty BindingNameProperty = DependencyProperty.Register("BindingName",
            typeof (string), typeof (DataStateBehavior), new PropertyMetadata(null));

        private BindingListener listener;

        private bool disposed;

        public DataStateBehavior()
        {
            this.listener = new BindingListener(this.HandleBindingValueChanged);

        }

        /// <summary>
        /// The binding to be used to evaluate the state.
        /// </summary>
        public Binding Binding
        {
            get { return (Binding) this.GetValue(DataStateBehavior.BindingProperty); }
            set { this.SetValue(DataStateBehavior.BindingProperty, value); }
        }

        /// <summary>
        /// The value to which the binding is compared against.
        /// </summary>
        public object Value
        {
            get { return (object) this.GetValue(DataStateBehavior.ValueProperty); }
            set
            {
                this.SetValue(DataStateBehavior.ValueProperty, value);
            }
        }

        /// <summary>
        /// The name of the VisualState tobe activated when true.
        /// </summary>
        public string FalseState
        {
            get { return (string) this.GetValue(DataStateBehavior.FalseStateProperty); }
            set { this.SetValue(DataStateBehavior.FalseStateProperty, value); }
        }

        /// <summary>
        /// The name of the VisualState tobe activated when false.
        /// </summary>
        public string TrueState
        {
            get { return (string) this.GetValue(DataStateBehavior.TrueStateProperty); }
            set { this.SetValue(DataStateBehavior.TrueStateProperty, value); }
        }

        /// <summary>
        /// The name of the VisualState tobe activated when false.
        /// </summary>
        public string BindingName
        {
            get { return (string) this.GetValue(DataStateBehavior.BindingNameProperty); }
            set { this.SetValue(DataStateBehavior.BindingNameProperty, value); }
        }

        private static void HandleBindingChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((DataStateBehavior) sender).OnBindingChanged(e);
        }

        /// <summary>
        /// Notification that the Binding property has changed.
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnBindingChanged(DependencyPropertyChangedEventArgs e)
        {
            if (this.listener != null)
            {
                this.listener.Binding = (Binding) e.NewValue;
            }

        }

        private static void HandleValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((DataStateBehavior) sender).OnValueChanged(e);
        }

        /// <summary>
        /// Notification that the Value property has changed.
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnValueChanged(DependencyPropertyChangedEventArgs e)
        {
            this.CheckState();
        }

        /// <summary>
        /// Implementation of OnAttached.
        /// </summary>
        protected override void OnAttached()
        {
            base.OnAttached();




            this.AssociatedObject.Unloaded += new RoutedEventHandler(AssociatedObject_Unloaded);
            this.listener.Element = this.AssociatedObject;
            this.LayoutUpdated += DataStateBehavior_LayoutUpdated;


        }

        private void DataStateBehavior_LayoutUpdated(object sender, object e)
        {
            this.LayoutUpdated -= DataStateBehavior_LayoutUpdated;
            var b = new Binding();
            b.Path = new PropertyPath(BindingName);
            b.Source = this.AssociatedObject.DataContext;
            this.Binding = b;
            //BindingOperations.SetBinding(this, BindingProperty, b);
        }


        private void AssociatedObject_Unloaded(object sender, RoutedEventArgs e)
        {
            this.AssociatedObject.Unloaded -= new RoutedEventHandler(AssociatedObject_Unloaded);
            //Dispose();
        }

        /// <summary>
        /// Implementation of OnDetaching.
        /// </summary>
        protected override void OnDetaching()
        {
            base.OnDetaching();

        }

        private void HandleBindingValueChanged(object sender, BindingChangedEventArgs e)
        {
            this.CheckState();
        }

        private void CheckState()
        {
            if (!disposed && AssociatedObject != null)
            {
                if (this.Value is string && this.Value.ToString() == "null" && this.listener.Value == null)
                {
                    this.IsTrue = true;
                    return;
                }

                if (this.Value == null || this.listener.Value == null)
                {
                    this.IsTrue = object.Equals(this.listener.Value, this.Value);
                }
                else
                {
                    this.IsTrue = ConverterHelper.CheckValues(this.Value, this.listener.Value);
                }
            }
        }

        private bool? isTrue;

        private bool? IsTrue
        {
            get { return this.isTrue; }
            set
            {
                if (this.isTrue != value)
                {
                    this.isTrue = value;

                    if (this.IsTrue.HasValue)
                    {

                        if (this.IsTrue.Value)
                            VisualStateManager.GoToState(AssociatedObject, this.TrueState, true);
                        else
                        {
                            if (!String.IsNullOrEmpty(this.FalseState))
                            {
                                VisualStateManager.GoToState(AssociatedObject, this.FalseState, true);
                            }
                        }

                    }
                }
            }
        }
    }
}
